# $Id$
# vim:et:ft=sh:sts=2:sw=2
#
# git-flow -- A collection of Git extensions to provide high-level
# repository operations for Vincent Driessen's branching model.
#
# A blog post presenting this model is found at:
#    http://blog.avirtualhome.com/development-workflow-using-git/
#
# Feel free to contribute to this project at:
#    http://github.com/petervanderdoes/gitflow
#
# Authors:
# Copyright 2012-2019 Peter van der Does. All rights reserved.
#
# Original Author:
# Copyright 2010 Vincent Driessen. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

initialize() {
	require_git_repo
	require_gitflow_initialized
	git config --get gitflow.prefix.support >/dev/null 2>&1 || die "Support prefix not set. Please run 'git flow init'."
	gitflow_load_settings
	VERSION_PREFIX=$(git config --get gitflow.prefix.versiontag)
	PREFIX=$(git config --get gitflow.prefix.support)
}

usage() {
		OPTIONS_SPEC="\
git flow support [list]
git flow support start

Manage your support branches.

For more specific help type the command followed by --help
--
"
	flags_help
}

cmd_default() {
	cmd_list "$@"
}

cmd_list() {
	OPTIONS_SPEC="\
git flow support [list] [-h] [-v]

List all local support branches
--
h,help!           Show this help
v,verbose         Verbose (more) output
"
	local support_branches current_branch width branch len
	local base master_sha branch_sha
	local tagname nicename

	# Define flags
	DEFINE_boolean 'verbose' false 'verbose (more) output' v

	# Parse arguments
	parse_args "$@"

	support_branches=$(git_local_branches_prefixed "$PREFIX")
	if [ -z "$support_branches" ]; then
		warn "No support branches exist."
		warn ""
		warn "You can start a new support branch:"
		warn ""
		warn "    git flow support start <name> <base>"
		warn ""
		exit 0
	fi
	current_branch=$(git_current_branch)

	# Determine column width first
	width=0
	for branch in $support_branches; do
		len=${#branch}
		width=$(max $width $len)
	done
	width=$(($width+3-${#PREFIX}))

	for branch in $support_branches; do
		base=$(git merge-base "$branch" "$MASTER_BRANCH")
		master_sha=$(git rev-parse "$MASTER_BRANCH")
		branch_sha=$(git rev-parse "$branch")
		if [ "$branch" = "$current_branch" ]; then
			printf "* "
		else
			printf "  "
		fi
		if flag verbose; then
			printf "%-${width}s" "${branch#$PREFIX}"
			if [ "$branch_sha" = "$master_sha" ]; then
				printf "(no commits yet)"
			else
				tagname=$(git name-rev --tags --no-undefined --name-only "$base")
				if [ "$tagname" != "" ]; then
					nicename=$tagname
				else
					nicename=$(git rev-parse --short "$base")
				fi
				printf "(based on $nicename)"
			fi
		else
			printf "%s" "${branch#$PREFIX}"
		fi
		echo
	done
}

cmd_help() {
	usage
	exit 0
}

# Parse arguments and set common variables
parse_args() {
	FLAGS "$@" || exit $?
	eval set -- "${FLAGS_ARGV}"

	# Read arguments into global variables
	if [ -z $1 ]; then
		VERSION=''
	else
		VERSION=$1
	fi

	if [ -z $2 ]; then
		BASE=''
	else
		BASE=$2
	fi
	BRANCH=$PREFIX$VERSION
}

cmd_start() {
	OPTIONS_SPEC="\
git flow support start [-h] [-F] <version> <base>

Start a new support branch name <version> based on <base>
--
h,help!           Show this help
showcommands!     Show git commands while executing them
F,[no]fetch       Fetch from origin before performing finish
"
	# Define flags
	DEFINE_boolean 'fetch' false "fetch from $ORIGIN before performing finish" F

	# Override defaults with values from config
	gitflow_override_flag_boolean   "support.start.fetch"   "fetch"

	# Parse arguments
	parse_args "$@"

	gitflow_require_version_arg
	gitflow_require_base_arg

	# Sanity checks
	git_config_bool_exists "gitflow.allowdirty" || require_clean_working_tree

	# Fetch remote changes
	if flag fetch; then
		git_fetch_branch "$ORIGIN" "$BASE"
	fi

	git_is_ancestor "$BASE" "$MASTER_BRANCH" || die "Given base '$BASE' is not a valid commit on '$MASTER_BRANCH'."

	require_branch_absent "$BRANCH"

	# Create branch
	git_do checkout -b "$BRANCH" "$BASE" || die "Could not create support branch '$BRANCH'."

	echo
	echo "Summary of actions:"
	echo "- A new branch '$BRANCH' was created, based on '$BASE'"
	echo "- You are now on branch '$(git_current_branch)'"
	echo
}

cmd_rebase() {
	OPTIONS_SPEC="\
git flow support rebase [-h] [-i] [-p] [<name|nameprefix>]

Rebase <name> on <base_branch>
--
h,help!                Show this help
showcommands!          Show git commands while executing them
i,[no]interactive      Do an interactive rebase
p,[no]preserve-merges  Preserve merges
"
	local opts

	# Define flags
	DEFINE_boolean 'interactive' false 'do an interactive rebase' i
	DEFINE_boolean 'preserve-merges' false 'try to recreate merges' p

	# Override defaults with values from config
	gitflow_override_flag_boolean   "support.rebase.interactive"       "interactive"
	gitflow_override_flag_boolean   "support.rebase.preserve-merges"   "preserve_merges"

	# Parse arguments
	parse_args "$@"

	# Use current branch if no version is given
	if [ "$VERSION" = "" ]; then
		gitflow_use_current_branch_version
	fi

	BASE_BRANCH=$(gitflow_config_get_base_branch $BRANCH)
	BASE_BRANCH=${BASE_BRANCH:-$DEVELOP_BRANCH}

	warn "Will try to rebase '$NAME' which is based on '$BASE_BRANCH'..."
	if ! git_config_bool_exists "rebase.autostash"; then
		require_clean_working_tree
	fi
	require_branch "$BRANCH"

	git_local_branch_exists "$BASE_BRANCH" || die "The base '$BASE_BRANCH' doesn't exists locally or is not a branch. Can't rebase the support branch '$BRANCH'."

	git_do checkout -q "$BRANCH"  || die "Could not check out branch '$BRANCH'."
	if flag interactive; then
		opts="$opts -i"
	fi
	if flag preserve_merges; then
		opts="$opts -p"
	fi
	git_do rebase $opts "$BASE_BRANCH"
}
